Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use templates for common geometric constants #7558

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

rubiefawn
Copy link
Contributor

@rubiefawn rubiefawn commented Oct 23, 2024

lmms_constants.h has several common constants such as PI and E, with variants of each for float, double, and long double. Many of these are currently unused in the repo but are of potential use. This change replaces LD_PI, D_PI, and F_PI with lmms::numbers::pi, and so on, in the style of C++20's <numbers>.

Currently, the constants are set using literal values, but once C++20 is fully ready these can be changed to their std::numbers::* equivalents instead.

@messmerd
Copy link
Member

You should use inline constexpr since the variables are in a header, though maybe it would be best to wait for C++20 (#7554) and GCC 10 where we'll get the <numbers> header.

Updated to account for `<numbers>` and C++20:
- Marked all `lmms_constants.h` constants with an exact equivalent in `<numbers>` as deprecated
- Removed all `lmms_constants.h` constants where no variant is currently in use
- Using `inline constexpr`
- Using `std::floating_point` concept instead of `typename`
@rubiefawn
Copy link
Contributor Author

Updated to account for <numbers> and C++20:

  • Marked all lmms_constants.h constants with an exact equivalent in <numbers> as deprecated
  • Removed all lmms_constants.h constants where no variant is currently in use
  • Using inline constexpr
  • Using std::floating_point concept instead of typename

@messmerd
Copy link
Member

messmerd commented Oct 23, 2024

This won't work. I suggested waiting for C++20 and the compiler upgrade since we are in the process of doing that now.

Currently we are using C++17 and GCC 9.3 for Linux and MinGW builds, so we can't use the <numbers> header or concepts yet.

If you wanted, maybe you could convert our mathematical constants to use the same names as those in <numbers>, but in the lmms::numbers namespace. Then once we upgrade to C++20, switching to <numbers> will be as easy as swapping out lmms::numbers::pi for std::numbers::pi. That may be quite a bit of work for you though, so it's up to you.

EDIT: The constants should probably be in a new lmms::numbers namespace to avoid collisions. It would basically just be a reimplementation of the parts of the numbers header that we use.

@rubiefawn rubiefawn marked this pull request as draft October 24, 2024 00:43
@rubiefawn
Copy link
Contributor Author

I'm aware that we don't have C++20 ready yet. I made the suggested changes (and more) in advance under the assumption that this PR was now dependent on #7554, based off of your suggestion. If this is not the case I can change it back, I'm good with whatever.

My original intention with this PR was small in scope; I just wanted to clean up lmms_constants.h. That being said, I love your suggestion for lmms::numbers, and if updating all usage of the constants is on the table, I'd love to explore that.

@messmerd
Copy link
Member

Ah gotcha. Sorry for the miscommunication. The C++20 support could happen tomorrow if people could review the PR, but upgrading our MinGW compiler and dependencies will be tricky and take some time.

I think the lmms::numbers idea would be good to implement. Function scope usages could use using namespace numbers; so that it doesn't need to be typed out fully as the clunkier numbers::pi or numbers::pi_v<float> in places where that would look better.
I'm not sure how big a task it would be, but it would probably be fairly easy with vscode or some other program to just search through src/, include/, and plugins/ and replace all.

@sakertooth
Copy link
Contributor

If I understand @messmerd correctly, I agree with him. We should wait for C++20, remove lmms_constants.h, and then just use the numeric library provided by the standard. The more code we can cut down and remove, I see as a win.

@rubiefawn
Copy link
Contributor Author

Just to clarify, there are several useful constants in lmms_constants.h that have no overlap with C++20 <numbers>. This PR isn't about removing that header entirely, it's just to clean it up. I agree with the "less is more" sentiment though.

On that note, I noticed panning_constants.h and panning.h and am wondering if those can be merged into one file (or even just moved to lmms_constants.h). Those could be considered further candidates for constant cleanup.

The current plan is to wait for #7554 before I make further changes. Input is welcome in the meantime!

@sakertooth
Copy link
Contributor

#7554 is here, so you can try and make the switch to the numbers header @rubiefawn (we have partial C++20 support, but I think we should have the numbers header at least).

On that note, I noticed panning_constants.h and panning.h and am wondering if those can be merged into one file (or even just moved to lmms_constants.h). Those could be considered further candidates for constant cleanup.

It's up to you really (or anyone else that wants to give it a go). I personally think it could go multiple ways with no apparent downside.

@messmerd
Copy link
Member

@sakertooth Nope, like most C++20 features, we're waiting for GCC 10.

See: https://en.cppreference.com/w/cpp/compiler_support/20
(Mathematical constants P0631R8)

@sakertooth
Copy link
Contributor

Hard to classify it as an upgrade then, but I guess it's a step in the right direction..

@messmerd
Copy link
Member

I'm using both class type NTTP and designated initializers in the pin connector now, so it's not nothing. Once I'm done with the pin connector, I'd like to upgrade to GCC 11 on Linux and MinGW 13 for the cross-compiled Windows builds. Then we'll have nearly all C++20 features including <numbers>.

@rubiefawn
Copy link
Contributor Author

This is the second time I've gotten duplicated commit history after pushing. Not sure if GitHub just doesn't like rebase or if it's a skill issue (likely the latter). How do I avoid this in the future?

@Rossmaxx
Copy link
Contributor

Don't worry, we do squash on merge.

@Rossmaxx
Copy link
Contributor

Wait, seems like lots of unnecessary diffs (from previously merged prs)

Moves the four constants in panning_constants.h into panning.h, then
removes panning.h.
@rubiefawn rubiefawn marked this pull request as ready for review November 28, 2024 07:27
Copy link
Contributor

@Rossmaxx Rossmaxx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some thoughts which came across when I looked at the diff.

include/BasicFilters.h Outdated Show resolved Hide resolved
include/BasicFilters.h Outdated Show resolved Hide resolved
include/lmms_constants.h Show resolved Hide resolved

const double w = 2 * LD_PI * freq / SR ;
const double PHI = pow( sin( w / 2 ), 2 ) * 4;
const double w = sin(numbers::pi * freq / Engine::audioEngine()->outputSampleRate());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You sure about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// original
const int SR = Engine::audioEngine()->outputSampleRate();
const double w = 2 * LD_PI * freq / SR ;
const double PHI = pow( sin( w / 2 ), 2 ) * 4;

// update LD_PI to new numbers::pi
const int SR = Engine::audioEngine()->outputSampleRate();
const double w = 2 * numbers::pi * freq / SR ;
const double PHI = pow( sin( w / 2 ), 2 ) * 4;

// SR is used only once, just use outputSampleRate() directly instead
const double w = 2 * numbers::pi * freq / Engine::audioEngine()->outputSampleRate();
const double PHI = pow( sin( w / 2 ), 2 ) * 4;

// w is used only once and is divided by 2, so the multiply by 2 cancels out
const double w = numbers::pi * freq / Engine::audioEngine()->outputSampleRate();
const double PHI = pow( sin( w ), 2 ) * 4;

// pow(x, 2) == x * x, simplify into multiplication expression
const double w = numbers::pi * freq / Engine::audioEngine()->outputSampleRate();
const double PHI = sin(w) * sin(w) * 4;

// no need to call sin(w) twice, just assign the sin()'d value to w in the first place
const double w = sin(numbers::pi * freq / Engine::audioEngine()->outputSampleRate());
const double PHI = w * w * 4;

I should have renamed w to make it clear it's not intended to have the exact same value as the previous code. Is that what you meant?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be a change in mathematical calculation. That's what I meant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm did some pen paper testing and the math checks out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also there's one thing you can do, make outputSampleRate into a member variable with initialisation in the constructor to avoid calling the function every time. It gets a bit lengthy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants